# @Time :  
# @Author : Fioman 
# @Phone : 13149920693
"""
mysql 单例类,所有的mysql的操作都在这个类里面.
首先这个类是单例类,再然后就是创建多个任务去创建更新数据库
"""
import datetime
import random
import threading
import time
from enum import Enum

import gevent

import settings
from db_tools.db_handler import DbHandler
from eap_mysql import mysql_access
from eap_mysql.mysql_logger import MysqlLogger
from eap_mysql.mysql_operator import MysqlOperator
from tools.send_to_ui_tools import send_order_state_to_ui, update_eap_params_to_ui, update_eap_table_data_to_ui

sqlLog = MysqlLogger()
db = DbHandler()


class EmpType(Enum):
    """
    员工上机下机的操作记录
    """
    INTIME = "上机时间"
    OUTTIME = "下机时间"


class MysqlHandler(object):
    """
    Mysql操作的单例类,线程安全的单例类
    """
    __instance__ = None
    __initFlag__ = False
    __lock__ = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if cls.__instance__ is None:
            with cls.__lock__:
                if cls.__instance__ is None:
                    cls.__instance__ = super(MysqlHandler, cls).__new__(cls)
        return cls.__instance__

    def __init__(self):
        if not self.__initFlag__:
            # 各个数据表的轮询周期
            self.pc_data_craft_duration = 60
            self.pc_data_manual_duration = 60
            self.pc_data_status_duration = 60
            self.pc_data_count_duration = 60
            self.pc_siginal_status_duration = 2
            self.eap_signal_status_duration = 2
            self.eap_material_data_duration = 2
            self.operation_mode = ""

            # 设备的运行状态
            self.camRunState = settings.RunState.Stop
            self.cbjRunState = settings.RunState.Stop
            self.cutterRunState = settings.RunState.Stop

            self.__initFlag__ = True
            sqlLog.debug("in MysqlHandler.__init__() 进行初始化")
            self.create_sql_table_used()
            self.reload_mes_sql_params()
            # 各个表开启线程进行扫描
            self.managerThread = threading.Thread(target=self.manager, name="managerT",
                                                  daemon=True)
            self.pcDataCraftThread = threading.Thread(target=self.pc_data_craft_listener,
                                                      name="pcDataCraftT", daemon=True)
            # self.pcDataManualThread = threading.Thread(target=self.pc_data_manual_listener,
            #                                            name="pcDataManualT", daemon=True)
            self.pcDataStatusThread = threading.Thread(target=self.pc_data_status_listener,
                                                       name="pcDataStatusT", daemon=True)
            self.eapSignalStatusThread = threading.Thread(target=self.eap_signal_status_listener,
                                                          name="eapSignalStatusT", daemon=True)

    def reload_mes_sql_params(self):
        """
        从数据库中从新加载数据库配置参数,主要是配置的一些轮询间隔
        @return:
        """
        try:
            res, data = db.get_eap_params()
            if res == "ok":
                self.pc_data_craft_duration = int(data.get("pc_data_craft", 60))
                self.pc_data_manual_duration = int(data.get("pc_data_manual", 60))
                self.pc_data_status_duration = int(data.get("pc_data_status", 60))
                self.pc_data_count_duration = int(data.get("pc_data_count", 60))
                self.pc_siginal_status_duration = int(data.get("pc_signal_status", 60))
                self.eap_signal_status_duration = int(data.get("eap_signal_status", 60))
                self.eap_material_data_duration = int(data.get("eap_material_data", 60))
                operation_mode = data.get("operation_mode", "本地模式")
                if self.operation_mode != operation_mode and self.operation_mode != "":
                    self.operation_mode = operation_mode
                    modeToEap = "1" if self.operation_mode == "Eap模式" else "0"
                    self.add_pc_signal_status_data(settings.PcSignal.AUTOMANUAL, modeToEap)
                else:
                    self.operation_mode = operation_mode
                self.auto_delete = False if data.get("delete_data_auto", "否") == "否" else True
                # 更新操作模式,底层是通过1或者0来控制的 Eap模式为1 本地模式为0
                sqlLog.debug(f"Eap参数加载,表轮询间隔: pc_data_craft: {self.pc_data_craft_duration}\n"
                             f"pc_data_manual_duration:{self.pc_data_manual_duration}\n"
                             f"pc_data_status:{self.pc_data_status_duration}\n"
                             f"pc_data_count_duration:{self.pc_data_count_duration}\n"
                             f"pc_siginal_status:{self.pc_siginal_status_duration}\n"
                             f"eap_signal_status:{self.eap_signal_status_duration}\n"
                             f"eap_material_data:{self.eap_material_data_duration}\n"
                             f"操作模式: {self.operation_mode},"
                             f"是否自动删除旧数据:{self.auto_delete}\n")
        except Exception as e:
            sqlLog.debug("in reload_mes_sql_params() error: {}".format(str(e)))

    @staticmethod
    def web_request_get_eap_params():
        """
        界面上请求sql的参数
        @return:
        """
        try:
            res, data = db.get_eap_params()
            return [data] if res == "ok" else []
        except Exception as e:
            sqlLog.debug("in web_request_sql_params()  error: {}".format(str(e)))
            return []

    @staticmethod
    def get_group_nubmer_int():
        """
        获取组号日期+6位流水号(随机的六位数)
        @return:
        """
        nowTime = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
        randomTwoStr = [str(random.randrange(0, 10)) for x in range(2)]
        return int(nowTime + "".join(randomTwoStr))

    @staticmethod
    def get_create_time():
        """
        获取创建时间,格式形如: yy-mm-dd hh:mm:ss
        @return:
        """
        return str(datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S"))

    def web_request_save_eap_params(self, newParams):
        """
        界面上点击了保存数据库轮询间隔设置表
        @param newParams:
        @return:
        """
        try:
            res, errorInfo = db.save_eap_params(newParams)
            if res == "ok":
                self.reload_mes_sql_params()
            return res if res == "ok" else errorInfo
        except Exception as e:
            sqlLog.debug("in web_save_sql_params() error: {}".format(str(e)))
            return str(e)

    def manager(self):
        """
        各个数据库监控线程的管理类
        @return:
        """
        while True:
            if not self.pcDataCraftThread.is_alive():
                self.pcDataCraftThread = threading.Thread(target=self.pc_data_craft_listener,
                                                          name="pcDataCraftT", daemon=True)
                self.pcDataCraftThread.start()

            # if not self.pcDataManualThread.is_alive():
            #     self.pcDataManualThread = threading.Thread(target=self.pc_data_manual_listener,
            #                                                name="pcDataManualT", daemon=True)
            #     self.pcDataManualThread.start()

            if not self.pcDataStatusThread.is_alive():
                self.pcDataStatusThread = threading.Thread(target=self.pc_data_status_listener,
                                                           name="pcDataCountT", daemon=True)
                self.pcDataStatusThread.start()

            if not self.eapSignalStatusThread.is_alive():
                self.eapSignalStatusThread = threading.Thread(target=self.eap_signal_status_listener,
                                                              name="eapSignalStatusT", daemon=True)
                self.eapSignalStatusThread.start()

            gevent.sleep(5)

    def pc_data_craft_listener(self):
        """
        pc_data_craft表更新,每隔一段时间去更新下pc_data_craft表内容
        删除旧表内容,更新新的表内容
        @return:
        """
        while settings.IS_MAIN_ALIVE:
            if self.operation_mode == "Eap模式":
                self.update_table_pc_data_craft()
                update_eap_table_data_to_ui("updatePcDataCraft")
            gevent.sleep(self.pc_data_craft_duration)

    # def pc_data_manual_listener(self):
    #     """
    #     pc_data_manualmaterial 表更新,每隔一段时间去更新下pc_data_manualmaterial表内容.
    #     删除旧表内容,更新新表内容
    #     @return:
    #     """
    #     while settings.IS_MAIN_ALIVE:
    #         if self.operation_mode == "Eap模式":
    #             # 设备的一些参数,上一次的和这一次的都要进行更新
    #             self.update_table_pc_data_manual()
    #         gevent.sleep(self.pc_data_manual_duration)

    def pc_data_status_listener(self):
        """
        pc_data_status 表更新,每隔一段时间去更新下pc_data_status 表内容.
        删除旧表内容,更新新表内容
        @return:
        """
        while settings.IS_MAIN_ALIVE:
            if self.operation_mode == "Eap模式":
                self.update_table_pc_data_status()
                update_eap_table_data_to_ui("updatePcDataStatus")
            gevent.sleep(self.pc_data_status_duration)

    def eap_signal_status_listener(self):
        """
        eap_signal_status 表的监控获取eap信号
        @return:
        """
        while settings.IS_MAIN_ALIVE:
            if self.operation_mode == "Eap模式":
                resList = mysql_access.get_eap_signal_status_data()
                if len(resList) != 0:
                    self.deal_eap_signal_status(resList)  # 去处理消息.
                update_eap_table_data_to_ui("updateEapSignalStatus")
            gevent.sleep(self.eap_signal_status_duration)

    @staticmethod
    def create_sql_table_used():
        """
        创建数据表
        @return:
        """
        mysql_access.create_table_pc_data_craft()
        mysql_access.create_table_pc_data_alarm()
        mysql_access.create_table_pc_data_status()
        mysql_access.create_table_pc_data_count()
        mysql_access.create_table_pc_signal_status()
        mysql_access.create_table_eap_signal_status()
        mysql_access.create_table_eap_material_data()
        mysql_access.create_table_pc_data_manualmaterial()
        mysql_access.create_table_pc_data_emp()

    def update_table_pc_data_craft(self):
        """
        工艺质量表数据插入
        @return:
        """
        try:
            insertData = self.get_data_craft_value()
            # 先去获取数据
            with MysqlOperator() as sp:
                tableName = "pc_data_craft"
                if self.auto_delete:
                    sp.delete_table_data(tableName)
                for data in insertData:
                    sql = ("insert into {} (CONTAINER,PNLIDORSETID, ITEMCODE, ITEMDES, UOM, ITEMVALUE, "
                           "ISOK, GROUPNUM, CREATETIME)"
                           " values (%s, %s, %s, %s, %s, %s, %s, %s,%s)").format(tableName)
                    sp.insert_data(sql, data)
        except Exception as e:
            sqlLog.debug("in update_table_pc_data_craft() error: {}".format(str(e)))

    def update_table_pc_data_status(self):
        """
        不实时采集的设备状态表更新
        @return:
        """
        try:
            insertData = self.get_table_pc_data_value()
            with MysqlOperator() as sp:
                tableName = "pc_data_status"
                if self.auto_delete:
                    sp.delete_table_data(tableName)
                for data in insertData:
                    sql = ("insert into {} (STATUSCODE,STATUSDES,STATUSVALUE,CREATETIME)"
                           " values (%s, %s, %s, %s)").format(tableName)
                    sp.insert_data(sql, data)
        except Exception as e:
            sqlLog.debug("in update_table_pc_data_status() error: {}".format(str(e)))

    def get_data_manual_value(self):
        """
        获取手动参数调整表
        @return:
        """
        data = db.get_working_info()[1]
        cutId = str(data.get("cutId", "默认物料号"))
        cutSpeed = str(data.get("cut_speed_work", 1000))
        dragSpeed = str(data.get("drag_speed", 300))
        workSpeed = str(data.get("fx_work_speed", 1000))
        cutSpeedLast = str(data.get("cut_speed_last", 1000))
        dragSpeedLast = str(data.get("drag_speed_last", 300))
        workSpeedLast = str(data.get("fx_work_speed_last", 1000))
        data = db.get_knife_cut_params()[1]
        cutDeep = str(data.get("cutDeep", 32))
        cutDeepLast = str(data.get("cutDeep_last", 32))
        isOkCutSp = "Y" if float(cutSpeed) < 1200 else "N"
        isOkDragSp = "Y" if float(dragSpeed) < 600 else "N"
        isOkWorkSp = "Y" if float(workSpeed) < 1200 else "N"
        isOkCutDeep = "Y" if float(cutDeep) < 50 else "N"
        createTime = self.get_create_time()
        res = [
            (cutId, "CUTSPEED", "切割速度", "mm/s", cutSpeedLast, cutSpeed, isOkCutSp, createTime),
            (cutId, "DRAGSPEED", "裁切机拖拽速度", "mm/s", dragSpeedLast, dragSpeed,
             isOkDragSp, createTime),
            (cutId, "WORKSPEED", "裁切机工作速度", "mm/s", workSpeedLast, workSpeed,
             isOkWorkSp, createTime),
            (cutId, "CUTDEEP", "下刀深度", "mm", cutDeepLast, cutDeep,
             isOkCutDeep, createTime),
        ]
        return res

    def get_data_craft_value(self):
        """
        获取工艺质量表的数据
        @return:
        """
        data = db.get_working_info()[1]
        cutId = str(data.get("cutId", "默认物料号"))
        knifeUsed = str(data.get("knifeUsed", "0"))
        tableUsed = str(data.get("tableUsedDays", "1"))
        cutterLifeUsed = data.get("cutter_life_used", "0")
        cutterKnifeName = data.get("cutter_knife_name", "Hd_Cutter_2024")
        pnlNum = data.get("pnlNum", "PNL001")
        data = db.get_cbj_zmc_params(db.cbjZmcParamsTable)[1]
        cutSpeed = str(data.get("cut_speed_work", 1000))
        dragSpeed = str(data.get("drag_speed", 300))
        workSpeed = str(data.get("fx_work_speed", 1000))
        data = db.get_knife_cut_params()[1]
        cutDeep = str(data.get("cutDeep", 32))

        isOkKnife = "Y" if float(knifeUsed) < 40000 else "N"
        isOkTable = "Y" if float(tableUsed) < 60 else "N"
        isOkCutSp = "Y" if float(cutSpeed) < 1200 else "N"
        isOkDragSp = "Y" if float(dragSpeed) < 600 else "N"
        isOkWorkSp = "Y" if float(workSpeed) < 1200 else "N"
        isOkCutDeep = "Y" if float(cutDeep) < 50 else "N"
        groupNum = self.get_group_nubmer_int()
        createTime = self.get_create_time()

        shiftData = db.get_shift_data()[1]
        runTime = shiftData.get("runTime", 0)
        idleTime = shiftData.get("idleTime", 0)
        alarmTime = shiftData.get("alarmTime", 0)
        pmTime = shiftData.get("pmTime", 0)
        prodCount = shiftData.get("prodCount", 0)

        res = [
            (cutId, pnlNum, "RUN_TIME", "当班运行时间", "min", runTime, "Y", groupNum, createTime),
            (cutId, pnlNum, "WAIT_TIME", "当班待机时间", "min", idleTime, "Y", groupNum, createTime),
            (cutId, pnlNum, "ALARM_TIME", "当班报警时间", "min", alarmTime, "Y", groupNum, createTime),
            (cutId, pnlNum, "MAINTAIN_TIME", "当班保养时间", "min", pmTime, "Y", groupNum, createTime),
            (cutId, pnlNum, "NUM_VALUE", "当班生产板数", "min", prodCount, "Y", groupNum, createTime),
            (cutId, pnlNum, "KNIFE_LIFE", "裁切刀已使用寿命", "min", cutterLifeUsed, "Y", groupNum, createTime),
            (cutId, pnlNum, "NIFE_NAME", "刀具条码", "min", cutterKnifeName, "Y", groupNum, createTime),
            (cutId, pnlNum, "CIRCULAR_KNIFE_LIFE", "圆刀使用寿命", "米(m)", knifeUsed, isOkKnife, groupNum, createTime),
            (cutId, pnlNum, "TABLECLOTH_TIME", "台布使用时间", "天(d)", tableUsed, isOkTable, groupNum, createTime),
            (cutId, pnlNum, "CUTTING_SPEED", "切割速度", "mm/s", cutSpeed, isOkCutSp, groupNum, createTime),
            (cutId, pnlNum, "TOWING_SPEED", "裁切机拖拽速度", "mm/s", dragSpeed, isOkDragSp, groupNum, createTime),
            (cutId, pnlNum, "WORWING_SPEED", "裁切机工作速度", "mm/s", workSpeed, isOkWorkSp, groupNum, createTime),
            (cutId, pnlNum, "DEPTH_CUT", "下刀深度", "mm", cutDeep, isOkCutDeep, groupNum, createTime)
        ]

        return res

    def get_table_pc_data_value(self):
        """
        获取不实时采集的设备状态数据
        @return:
        """
        createTime = self.get_create_time()
        data1 = ("CAMZMCRUNNING", "上料控制器运行/停止", str(self.camRunState.value), createTime)
        data2 = ("CBJZMCRUNNING", "裁切机控制器运行/停止", str(self.cbjRunState.value), createTime)
        data3 = ("CUTTERZMCRUNNING", "铡刀控制器运行/停止", str(self.cutterRunState.value), createTime)
        data = db.get_working_info()[1]
        orderUsedKey = data.get("orderUsedKey", "1")
        orderData = db.get_order_by_key(orderUsedKey)
        jointNumber = orderData.get("joint_number", "2")
        firstEdge = str(orderData.get("topEdge", 15))
        secondEdge = str(orderData.get("leftEdge", 15))
        thirdEdge = str(orderData.get("bottomEdge", 15))
        fourthEdge = str(orderData.get("fourthEdge", 15))
        cutId = str(orderData.get("id", "Test001"))
        finishNumber = str(orderData.get("amount", 0))
        data4 = ("JOINTNUMBER", "当前作业板拼接类型", jointNumber, createTime)
        data5 = ("FIRSTEDGE", "第一刀留边宽度", firstEdge, createTime)
        data6 = ("SECONDEDGE", "第二刀留边宽度", secondEdge, createTime)
        data7 = ("THIRDEDGE", "第三刀留边宽度", thirdEdge, createTime)
        data8 = ("FORTHEDGE", "第四刀留边宽度", fourthEdge, createTime)
        data9 = ("CUTID", "当前作业的物料号", cutId, createTime)
        data10 = ("FINISHNUMBER", "当前工单已生产数量", finishNumber, createTime)
        return [data1, data2, data3, data4, data5, data6, data7, data8, data9, data10]

    @staticmethod
    def add_pc_signal_status_data(signalType, signalVal):
        """
        pc中设备实时信号表更新.每次只插入一条数据
        @param signalType:
        @param signalVal:
        @return:
        """
        createTime = MysqlHandler.get_create_time()
        data = None
        signalVal = "{}".format(signalVal)  # 转换为字符串
        if signalType == settings.PcSignal.POWER:
            data = ("POWER", "设备上机/停机", signalVal, createTime)
        elif signalType == settings.PcSignal.PRODUCT:
            data = ("PRODUCT", "生产开始/结束", signalVal, createTime)
        elif signalType == settings.PcSignal.WAITMATERIAL:
            data = ("WAITMATERIAL", "设备待料", signalVal, createTime)
        elif signalType == settings.PcSignal.TOTALALARM:
            data = ("TOTALALARM", "设备总故障状态", signalVal, createTime)
        elif signalType == settings.PcSignal.EMERGENCYSTOP:
            data = ("EMERGENCYSTOP", "紧急停止", signalVal, createTime)
        elif signalType == settings.PcSignal.STOPLINE:
            data = ("STOPLINE", "设备重大故障(停线故障)", signalVal, createTime)
        elif signalType == settings.PcSignal.AUTOMANUAL:
            data = ("AUTOMANUAL", "自动/手动模式", signalVal, createTime)
        elif signalType == settings.PcSignal.MATERIALOK:
            data = ("MATERIALOK", "设备通知EAP资料加载完毕", signalVal, createTime)
        elif signalType == settings.PcSignal.UPDATEPLANOK:
            data = ("UPDATEPLANOK", "通知EAP任务修改完毕", signalVal, createTime)
        elif signalType == settings.PcSignal.DELETEPLANOK:
            data = ("DELETEPLANOK", "通知EAP任务删除完毕", signalVal, createTime)
        elif signalType == settings.PcSignal.SCANLOTUPLOAD:
            data = ("SCANLOTUPLOAD", "设备通知EAP扫描LOT号", signalVal, createTime)

        try:
            with MysqlOperator() as sp:
                tableName = "pc_signal_status"
                sql = ("insert into {} (SIGNALCODE,SIGNALDES,SIGNALVALUE,CREATETIME)"
                       " values (%s, %s, %s, %s)").format(tableName)
                sp.insert_data(sql, data)
        except Exception as e:
            sqlLog.debug("in add_pc_signal_status_data() error: {}".format(str(e)))

        # 每次新加一个信号的时候,都更新到UI界面
        update_eap_table_data_to_ui("updatePcSignalStatus")

    def deal_eap_signal_status(self, eapSignalData):
        """
        处理eapSignalData的数据
        @param eapSignalData:
        @return:
        """
        sqlLog.debug(f"接收到EapSignalStatus,接收到的数据Data: \n{eapSignalData}")
        try:
            for data in eapSignalData:
                signalCode = data["SIGNALCODE"]
                signalValue = data["SIGNALVALUE"]
                if signalCode == "MATERIALDOWN" and signalValue == "1":
                    debugInfo = f"接收到Eap信号: Eap通知设备资料下发完毕."
                    self.deal_plan_download()  # 加载任务
                    # 删除这个表数据内容
                    mysql_access.delete_meterial_data()
                elif signalCode == "UPDATEPLAN":
                    debugInfo = f"接收到Eap信号: 通知设备计划修改,lot号;lot数量"
                    self.deal_update_plan(signalValue)
                elif signalCode == "DELETEPLAN":
                    debugInfo = f"接收到Eap信号: 通知设备计划删除"
                elif signalCode == "MATERIALERROR":
                    debugInfo = f"接收到Eap信号: 通知设备资料下发异常: {signalValue:}"
                else:
                    debugInfo = f"接收到Eap信号: 未定义信号: {signalCode}"
                sqlLog.debug(debugInfo)
                fieldName = "SIGNALCODE"
                mysql_access.delete_eap_signal_record_by_field(fieldName, signalCode)
        except Exception as e:
            sqlLog.debug("in deal_eap_signal_status() error: {}".format(str(e)))

    def deal_plan_download(self):
        """
        工单切换的任务.
        @return:
        """
        # 1. 获取工单资料表的内容
        orderList = mysql_access.get_eap_material_data_data()
        sqlLog.debug("获取EAP_METERIAL_DATA的数据内容:{}".format(orderList))
        materialRes = "1"
        if len(orderList) >= 3:
            width = None
            height = None
            cropThickness = None
            jointNumber = None
            layoutMode = None
            lotId = None
            recipeId = None
            planCount = None
            for data in orderList:
                lotId = data["CONTAINER"]
                recipeId = data["PRODUCT"]
                planCount = data["COUNT"]
                itemCode = data["ITEMCODE"]
                itemValue = data["ITEMVALUE"]
                if itemCode == "PNL_LENGTH":
                    width = float(itemValue)
                elif itemCode == "PNL_WIDTH":
                    height = float(itemValue)
                elif itemCode == "CropperThickness":
                    cropThickness = float(itemValue)
                # elif itemCode == "JointNumber":
                #     jointNumber = itemValue
                # elif itemCode == "LayoutMode":
                #     layoutMode = itemValue
            if all([width, height, cropThickness, lotId, recipeId, planCount]):
                # 根据宽和高去查询对应的拼板数量和排板方式,如果不存在要弹窗提示
                query = {
                    "width": width,
                    "height": height,
                }
                res, data = db.get_data_one(db.sizeLayoutTable, query)
                if res != "ok":
                    errorInfo = (f"Eap工单下发失败: 此工单尺寸对应的拼板方式和排板方式在本地没有配置")
                    sqlLog.debug(errorInfo)
                    update_eap_table_data_to_ui("sizeLayoutNotFound")
                    materialRes = "2"
                else:
                    jointNumber = data.get("joint_number")
                    layoutMode = data.get("layout")
                    # 去做切换工单的流程,创建一个新工单,然后通知前端去更新这个工单,并且js那里也要去更新
                    self.create_new_order_from_eap(lotId, recipeId, width, height,
                                                   cropThickness, jointNumber, layoutMode, planCount)
            else:
                errorInfo = (f"工单数据解析失败: width={width},height={height},"
                             f"cropThickness={cropThickness},jointNumber={jointNumber},"
                             f"laymode={layoutMode},lotId={lotId},recipeId={recipeId}")
                sqlLog.debug(errorInfo)
                materialRes = "2"
        else:
            erronInfo = (f"工单数据解析失败,eap_material_data数据表内容的长度为{len(orderList)},"
                         f"正确的数据项应该有5条才对,不符合要求")
            materialRes = "2"
            sqlLog.debug(erronInfo)
        self.add_pc_signal_status_data(settings.PcSignal.MATERIALOK, materialRes)

    def create_new_order_from_eap(self, lotId, recipeId, width, height, cropThickness,
                                  jointNumber, layoutMode, planCount):
        """
        创建一个新工单,并且更新到前端,后台.关键是后台如何更新,根据这里面一个变量,就是工单切换的变量
        @param lotId:
        @param recipeId:
        @param width:
        @param height:
        @param cropThickness:
        @param jointNumber:
        @param layoutMode:
        @return:
        """
        if 0 < cropThickness <= 0.33:
            cropThickness = "0 ~ 0.33"
        elif 0.33 < cropThickness <= 1:
            cropThickness = "0.34 ~ 1"
        elif 1 < cropThickness <= 1.5:
            cropThickness = "1.1 ~ 1.5"
        elif 1.5 < cropThickness <= 2:
            cropThickness = "1.6 ~ 2"
        else:
            cropThickness = "2 ~ "

        tableName = "order"
        insertKey = int(time.time())
        data = {
            "key": insertKey,
            "order_id": recipeId,
            "lotId": lotId,  # 批次号
            "width": width,
            "height": height,
            "cropper_thickness": cropThickness,
            "top_edge": 15,
            "left_edge": 15,
            "bottom_edge": 15,
            "right_edge": 15,
            "calc_height": 0,
            "calc_width": 0,
            "is_break": "否",
            "layout": layoutMode,
            "amount": 0,
            "planCount": planCount,  # 计划生产数量
            "joint_number": jointNumber
        }
        db.insert_data(tableName, data)  # 先插入到数据库
        # 更新工单,首先是界面上更新工单.
        msgVal = {
            "val": insertKey
        }
        send_order_state_to_ui(msgVal)  # 前端更新
        settings.orderDownloadFromEap = data  # 更新这个值,这个值每次工单更新之后就设置为None
        # 如果不为None,就将这个工单进行切换.
        # 工单切换完之后就删除掉之前的数据
        mysql_access.delete_meterial_data()

    def deal_update_plan(self, lotInfo):
        """
        计划修改,修改lot号对应的数量
        @param lotInfo:
        @return:
        """
        sqlLog.debug(f"收到Eap信号 UPDATEPLAN: EAP通知设备计划修改,SIGNALVALUE: {lotInfo}")
        updateRes = "1"  # 1表示成功 2表示失败
        try:
            lotId, newPlanCount = lotInfo.split(";")
            # 根据lotId去查询是否存在这个工单
            query = {
                "order_id": lotId
            }
            _, resList = db.get_data_list(db.orderTable, query)

            if len(resList) == 0:
                updateRes = "2"
            else:
                newValues = {
                    "$set": {
                        "planCount": int(newPlanCount)
                    }
                }
                db.update_data(db.orderTable, query, newValues)
                updateRes = "1"
                data = db.get_working_info()[1]
                orderUsedKey = data.get("orderUsedKey", "1")
                msgVal = {
                    "val": orderUsedKey
                }
                send_order_state_to_ui(msgVal)  # 更新前端界面
        except Exception as e:
            sqlLog.debug(f"in deal_update_plan() error: {e}")
            updateRes = "2"
        finally:
            self.add_pc_signal_status_data(settings.PcSignal.UPDATEPLANOK, updateRes)

    def add_user_emp_record(self, empInfo):
        """
        增加员工的操作记录上下机的操作记录,前端界面调用
        @param empInfo:emp上报的信息,列表类型
        @return:
        """
        empno, empname, empcode = empInfo
        if empno == "":
            return "员工工号不能为空"
        if self.operation_mode == "本地模式":
            return "上下机操作上报失败,当前模式是本地模式,非Eap模式,请替换为Eap模式进行上报"
        empTime = MysqlHandler.get_create_time()
        createTime = self.get_create_time()
        empcodeEnum = EmpType(empcode)
        empcode = empcodeEnum.name
        empDes = empcodeEnum.value
        data = (empno, empname, empcode, empDes, empTime, createTime)
        try:
            with MysqlOperator() as sp:
                tableName = "pc_data_emp"
                sql = ("insert into {} (EMPNO,EMPNAME,EMPCODE,EMPDES,EMPTIME,CREATETIME)"
                       " values (%s, %s, %s, %s,%s,%s)").format(tableName)
                sp.insert_data(sql, data)
        except Exception as e:
            sqlLog.debug("in add_user_emp_record() error: {}".format(str(e)))

        update_eap_table_data_to_ui("updatePcDataEmp")
        return "ok"

    def add_pc_alarm_data(self, signalType, signalVal):
        """
        pc中设备实时信号表更新.每次只插入一条数据
        @param signalType:
        @param signalVal:
        @return:
        """
        if self.operation_mode == "本地模式":
            return
        createTime = MysqlHandler.get_create_time()
        signalVal = "{}".format(signalVal)  # 转换为字符串
        data = (signalType.name, signalType.value, signalVal, createTime)
        try:
            with MysqlOperator() as sp:
                tableName = "pc_data_alarm"
                sql = ("insert into {} (ALARMCODE,ALARMDES,ALARMVALUE,CREATETIME)"
                       " values (%s, %s, %s, %s)").format(tableName)
                sp.insert_data(sql, data)
        except Exception as e:
            sqlLog.debug("in add_pc_alarm_data() error: {}".format(str(e)))

        # 每次添加一个报警信息的时候,都更新一下界面
        update_eap_table_data_to_ui("updatePcDataAlarm")

    def pc_data_manual_insert_data(self, data):
        """
        更新手动参数调整表
        @return:
        """

        try:
            # 先去获取数据
            with MysqlOperator() as sp:
                tableName = "pc_data_manualmaterial"
                if self.auto_delete:
                    sp.delete_table_data(tableName)
                sql = ("insert into {} (CONTAINER, ITEMCODE, ITEMDES, UOM,"
                       " OLDITEMVALUE,NEWITEMVALUE, "
                       "ISOK, CREATETIME)"
                       " values ( %s, %s, %s, %s, %s, %s, %s,%s)").format(tableName)
                sp.insert_data(sql, data)
                update_eap_table_data_to_ui("updatePcDataManual")
        except Exception as e:
            sqlLog.debug("in update_table_pc_data_craft() error: {}".format(str(e)))

    @staticmethod
    def send_eap_init_state_toui():
        """
        将各个表的初始化状态发送到前端
        @return:
        """
        update_eap_params_to_ui()

        update_eap_table_data_to_ui("updatePcDataCraft")
        update_eap_table_data_to_ui("updatePcDataManual")
        update_eap_table_data_to_ui("updatePcDataAlarm")
        update_eap_table_data_to_ui("updatePcDataStatus")
        update_eap_table_data_to_ui("updatePcDataEmp")
        update_eap_table_data_to_ui("updatePcDataCount")
        update_eap_table_data_to_ui("updatePcSignalStatus")
        update_eap_table_data_to_ui("updateEapSignalStatus")
        update_eap_table_data_to_ui("updateSizeLayoutData")

    def handle_send_lot_to_eap(self, lotId):
        """
        处理扫码工单的信号
        @param lotId:
        @return:
        """
        if lotId == "":
            return "请求的扫码lotid不能为空,请重新扫描"
        self.add_pc_signal_status_data(settings.PcSignal.SCANLOTUPLOAD, lotId)
        return "ok"

    def save_size_layout_data(self, newData):
        tableName = db.sizeLayoutTable
        newKey = newData["key"]
        query = {
            "key": newKey,
        }
        res, data = db.get_data_one(tableName, query)
        if res == "ok":

            newValues = {
                "$set": newData
            }
            res = db.update_data(tableName, query, newValues)[0]

        else:
            res = db.insert_data(tableName, newData)[0]
        update_eap_table_data_to_ui("updateSizeLayoutData")
        return res

    @staticmethod
    def get_sizelayout_data():
        update_eap_table_data_to_ui("updateSizeLayoutData")

    def delete_size_layout_data(self, deleteKey):
        tableName = db.sizeLayoutTable
        query = {
            "key": deleteKey
        }
        res, info = db.delete_data(tableName, query)
        update_eap_table_data_to_ui("updateSizeLayoutData")
        return "ok" if res == "ok" else info


if __name__ == '__main__':
    a = EmpType("上机时间")
    print(a, type(a))
    print(a.name)
    print(a.value)
